﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Course1
{
    public class Father
    {
        public int _age;
        public int Age { get { return _age; } set { _age = value; } }
        /// <summary>
        /// C#中只有虚函数才能重写
        /// </summary>
        public virtual void SayAge()
        {
            Console.WriteLine("我的高龄是：" + Age);//老气
        }
        public virtual void SayPrivateAge()
        {
            Console.WriteLine("我的高龄是：" + _age);//老气
        }
        public void SayFatherHello()
        {
            Console.WriteLine("我是父亲");
        }
        public Father()
        {
            Console.WriteLine("Father的无参数构造器被调用");
            _age = 1;
        }
        public Father(int age)
        {
            Console.WriteLine("Father的(age)构造器被调用");
            _age = age;
        }
    }
    /// <summary>
    /// 继承
    /// 1.继承只讨论实列成员，静态成员不存在继承的说法，无需讨论
    /// 2.继承可以理解成复制了父类的所有的代码，但是子类中只能访问到父类中的公开成员(不代表没有)
    /// 3.所有类都间接或者直接基础了object
    /// 4.继承的本质就是子类复制了父类的所有代码
    /// </summary>
    public class Children : Father
    {
        /// <summary>
        /// 函数重写
        /// 1.发生在子类和父类之间，子类重写（覆盖）父类的方法
        /// </summary>
        public override void SayAge()
        {
            base.SayAge();//由于子类继承了父类的所以方法，相当于复制了一份过来，为了区分可以通过base来调用父类成员
            this.SayAge();//明确调用自己的
            SayAge();//和前面加this的意义相同，但是这两种写法都有问题，递归了。
            Console.WriteLine("我" + Age + "岁了");//幼气
            //间接调用_age；
            SayPrivateAge();//可以说调用（间接）父类的的SayAge2()也可以说是自己的，因为继承了就是我的了，证明私有成员也有，只是不能之间访问到
            base.SayPrivateAge();//明确调用父类的
            this.SayPrivateAge();//明确调用我的，由于没有重写因此，三种写法意义相同
        }
        /// <summary>
        /// 这个不叫重写，叫覆盖
        /// </summary>
        public new void SayFatherHello()
        {
            Console.WriteLine("我是父亲");
        }
        public Children()
            :base()//调用父类的默认构造器
        {

        }
        public Children(int age)
            : base(age)//调用父类的构造器来完成对age的初始化
        {

        }
    }

    internal class Example3
    {

        public void Test()
        {
            var cc = new Children();
            cc.SayFatherHello();//调用父类的实函数
            Console.WriteLine(cc.Age);//调用父类的实列属性
            cc.SayPrivateAge();//调用父类的需函数，没重写
            cc.SayAge();//调用重写父类的函数
            if (cc is Father)//判断是否可以转换，即判断继承关系（判断变量c是否是Father的派生类）
            {
                
            }
            //如果成功返回fa，否则返回null
            var fa = cc as Father;
            //失败将引发异常
            var fa1 = (Father)cc;
        }
        /// <summary>
        /// 多态
        /// </summary>
        public void Test2()
        {
            //父类型的引用可以指向子类型的对象
            //多态的前提是子类继承了父类所有的代码，拥有父类的所有能力
            Father f = new Children();
            //编译阶段（编码阶段）函数由引用的类型决定（即f只能点出来Father中的函数）F12会跳到父类里
            //运行阶段函数有指向的对象的类型决定，运行时会指向Children中的代码
            f.SayAge();//
            object f1 = f;
            //强制类型转换成功的前提必须得有继承关系，即f1指向的对象和Children存在继承关系
            Children c1 = (Children)f1;//合法
            Father c2 = (Father)f1;//合法
            FileStream c3 = (FileStream)f1;//非法，f1指向的对象的类型是Children和FileStream不存在继承关系。
            if (f1 is FileStream)
            {
                FileStream c4 = (FileStream)f1;//检查是否能进行转换
            }
            if (f1 is FileStream file)//如果成功指向if语句块，file是转换之后的FileStream的指针
            {

            }
        }

    }
}
